﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Drive.DbAccess
{
    public class ValueConvert
    {
        public static object Convert<T>(T val, Type dstType)
        {
            if (dstType.IsAssignableFrom(typeof(T)))
            {
                return val;
            }

            var typeCode = Type.GetTypeCode(dstType);
            switch (typeCode)
            {
                case TypeCode.Object:
                    if (dstType == typeof(Guid))
                    {
                        return ObjectToGuid(val);
                    }
                    else if (dstType.IsGenericType && dstType.GetGenericTypeDefinition() == typeof(Nullable<>))
                    {
                        return Convert(val, dstType.GetGenericArguments()[0]);
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }
                case TypeCode.DBNull:
                    return null;
                case TypeCode.Boolean:
                    return ObjectToBoolen(val);
                case TypeCode.Char:
                    return ObjectToChar(val);
                case TypeCode.SByte:
                    return ObjectToSByte(val);
                case TypeCode.Byte:
                    return ObjectToByte(val);
                case TypeCode.Int16:
                    return ObjectToInt16(val);
                case TypeCode.UInt16:
                    return ObjectToUInt16(val);
                case TypeCode.Int32:
                    return ObjectToInt32(val);
                case TypeCode.UInt32:
                    return ObjectToUInt32(val);
                case TypeCode.Int64:
                    return ObjectToLong(val);
                case TypeCode.UInt64:
                    return ObjectToULong(val);
                case TypeCode.Single:
                    return ObjectToSingle(val);
                case TypeCode.Double:
                    return ObjectToDouble(val);
                case TypeCode.Decimal:
                    return ObjectToDecimal(val);
                case TypeCode.DateTime:
                    return ObjectToDateTime(val);
                case TypeCode.String:
                    return ObjectToString(val);
                default:
                    return null;
            }
        }

        private static object ObjectToString(object val)
        {
            return val?.ToString();
        }

        private static object ObjectToUInt32(object val)
        {
            if (uint.TryParse(val?.ToString(), out var l))
            {
                return l;
            }
            return null;
        }
        private static object ObjectToInt32(object val)
        {
            if (int.TryParse(val?.ToString(), out var l))
            {
                return l;
            }
            return null;
        }
        private static object ObjectToInt16(object val)
        {
            if (Int16.TryParse(val?.ToString(), out var l))
            {
                return l;
            }
            return null;
        }

        private static object ObjectToUInt16(object val)
        {
            if (UInt16.TryParse(val?.ToString(), out var l))
            {
                return l;
            }
            return null;
        }

        private static object ObjectToLong(object val)
        {
            if (long.TryParse(val?.ToString(), out long l))
            {
                return l;
            }
            return null;
        }

        private static object ObjectToULong(object val)
        {
            if (ulong.TryParse(val?.ToString(), out var l))
            {
                return l;
            }
            return null;
        }

        private static object ObjectToSingle(object val)
        {
            if (Single.TryParse(val?.ToString(), out var l))
            {
                return l;
            }
            return null;
        }

        private static object ObjectToDateTime(object val)
        {
            if (DateTime.TryParse(val?.ToString(), out DateTime t))
            {
                return t;
            }
            return null;
        }

        private static object ObjectToGuid(object val)
        {
            if (Guid.TryParse(val?.ToString(), out Guid guid))
            {
                return guid;
            }
            return null;
        }

        private static object ObjectToDouble(object val)
        {
            if (double.TryParse(val?.ToString(), out var d))
            {
                return d;
            }
            return null;
        }

        private static object ObjectToDecimal(object val)
        {
            if (decimal.TryParse(val?.ToString(), out var d))
            {
                return d;
            }
            return null;
        }

        private static object ObjectToBoolen(object val)
        {
            if (bool.TryParse(val?.ToString(), out var d))
            {
                return d;
            }
            return null;
        }

        private static object ObjectToSByte(object val)
        {
            if (sbyte.TryParse(val?.ToString(), out var d))
            {
                return d;
            }
            return null;
        }

        private static object ObjectToByte(object val)
        {
            if (byte.TryParse(val?.ToString(), out var d))
            {
                return d;
            }
            return null;
        }

        private static object ObjectToChar(object val)
        {
            if (char.TryParse(val?.ToString(), out var d))
            {
                return d;
            }
            return null;
        }

    }
}
